/*
	QUBE
	Sandra Obermann - QPT 1 - 2012
	fhs33730 - 1110601021
	FH Salzburg - Studiengang MultiMediaTechnolgy
*/

// Cinder Includes
#include "cinder/Utilities.h"

// Own written Includes
#include "../include/DataManager.h"

// Initialize DataManager* with NULL
DataManager* DataManager::m_Instance = NULL;

// Gets a single instance of the DataManger until the Game is closed
DataManager* DataManager::getInstance()
{
	if ( m_Instance == NULL )
	{
		m_Instance = new DataManager();
	}

	return m_Instance;
}

// Deletes the single instance of the DataManager when the Game is closed
void DataManager::releaseInstance()
{
	delete m_Instance;
	m_Instance = NULL;
}

// Initialize DataMananger with default values and start functions
DataManager::DataManager()
{
	m_MaxTimeToChangeQubeColor = 1.5f;
	m_level = new Level();
	m_fonts = new FontDisplay();
	m_timer = new QubeTimer();
	m_background = new Background(700);

	// Set Game Bools
	setGameFinished(false);
	setGameOver(false);
}

// Destructor for DataManager element which deletes the level, the fonts and the time
DataManager::~DataManager()
{
	killLevel();
	if(m_level)
	{
		delete m_level;
	}
	if(m_fonts)
	{
		delete m_fonts;
	}
	if(m_timer)
	{
		delete m_timer;
	}
	if( m_Qube )
	{
		delete m_Qube;
	}
	if( m_background )
	{
		delete m_background;
	}
}

// Calls the font create function
void DataManager::initFonts()
{
	if(m_fonts)
	{
		m_fonts->buildFontDisplay();
	}
}

// Adds new QUBE Colors to the Color Array
void DataManager::addQubeColor( ci::Color color )
{
	m_QubeColors.push_back( color );
}

// Returns the numbers of colors
unsigned int DataManager::getQubeColorsSize() const
{
	return m_QubeColors.size();
}

// Returns the Index of the Color
ci::Color DataManager::getQubeColor( unsigned int index ) const
{
	return m_QubeColors[index];
}

// Returns the max time for changing the color
float DataManager::getMaxTimeToChangeQubeColor() const
{
	return m_MaxTimeToChangeQubeColor;
}

// Build the Game Level
void DataManager::buildLevel()
{
	if( m_level )
	{
		m_level->buildLevel();
	}
}

// Return if there is a BLOCK or not
BLOCK* DataManager::getLevelBlock( int x, int y, int z )
{
	if( m_level )
	{
		return m_level->getLevelBlock( x, y, z );
	}

	return 0;
}

// Kill the Game Level
void DataManager::killLevel()
{
	if( m_level )
	{
		m_level->killLevel();
	}
}

// Draw the Game Level
void DataManager::drawLevel()
{
	if( m_level )
	{
		m_level->drawLevel();
	}
}

void DataManager::isFinishedLevel()
{
	ci::Vec3f finishBlock = m_level->getFinishPosition();
	finishBlock.y += 5;
	
	if(m_Qube->getQubePosition() == finishBlock)
	{
		// zoom out of the screen
		m_currentCameraPosition.x -= 1.25f;
		m_currentCameraPosition.y += 1.60f;
		m_currentCameraPosition.z += 1.00f;

		// set finish bool and stop game time
		setGameFinished(true);
		m_timer->stopSessionTime();
	}
}

// Draw the Fonts
void DataManager::drawFont( E_FONT_ID fontID )
{
	if( m_fonts )
	{
		m_fonts->drawFontDisplay(fontID);
	}
}

// Returns the Time
QubeTimer* DataManager::getTimer()
{
	return m_timer;
}

QUBE* DataManager::getQube()
{
	return m_Qube;
}

void DataManager::setupQube()
{
	// Init QUBE
	m_Qube = new QUBE( 5 );
	m_Qube->setup();
}

void DataManager::drawQube()
{
	m_Qube->draw();
}

void DataManager::updateQube()
{
	m_Qube->update( (float)m_timer->getDeltaTime() );
}

void DataManager::moveQubeToDir( QUBE_MOVEMENT dir )
{
	m_Qube->moveToDir(dir);
}

void DataManager::setGameOver(bool flag)
{
	m_gameOver = flag;
}
void DataManager::setGameFinished(bool flag)
{
	m_finished = flag;
}

bool DataManager::isGameOver()
{
	return m_gameOver;
}

bool DataManager::isGameFinished()
{
	return m_finished;
}

void DataManager::resetGame()
{
	// Start New Game and reset game over bool, finished bool, the time and set the QUBE to start position
	setGameOver(false);
	setGameFinished(false);
	m_timer->resetSessionTime();
	m_currentCameraPosition = Vec3f(15, E_LEVEL_2, 20);
	m_Qube->setQubePosition( Vec3f( 15, E_LEVEL_2, 20 ) );
}

void DataManager::setupCamera()
{
	// Camera perspective properties
	float cameraFOV = 45.0f;
	float cameraNear = 1.0f;
	float cameraFar = 10000;

	m_cameraPerspective = ci::CameraPersp( getWindowWidth(), getWindowHeight(), cameraFOV );

	m_cameraPerspective.setWorldUp( ci::Vec3f(0, 1, 0) );
	m_cameraPerspective.setEyePoint( ci::Vec3f(0, 0, 0 ) );
	m_cameraPerspective.setCenterOfInterestPoint( ci::Vec3f::zero() );
	m_cameraPerspective.setPerspective( cameraFOV, getWindowAspectRatio(), cameraNear, cameraFar );
	m_cameraPerspective.setViewDirection( ci::Vec3f(0, 0, 1 ) );

	m_currentCameraPosition = Vec3f::zero(); // Start position of the QUBE
}

void DataManager::updateCamera()
{
	// Set camera lookAt and attach Camera to QUBE Movement
	m_currentCameraPosition = lerp<Vec3f, float>( m_currentCameraPosition, m_Qube->getQubePosition(), 0.016f );

	m_cameraPerspective.lookAt( Vec3f( m_currentCameraPosition.x - 35.0f, m_currentCameraPosition.y + 60.0f, m_currentCameraPosition.z + 50.0f ),
								Vec3f( m_currentCameraPosition.x, m_currentCameraPosition.y, m_currentCameraPosition.z ),
								Vec3f( 0.0f, 1.0f, 0.0f ) );
}

void DataManager::resizeCamera(ResizeEvent event)
{
	m_cameraPerspective.setPerspective( 45.0f, event.getAspectRatio(), 1.0f, 1000.0f );
}

CameraPersp DataManager::getCameraPersp()
{
	return m_cameraPerspective;
}

void DataManager::drawBackground()
{
	m_background->drawBackground();
}